﻿using MessageWorkflow.Graph;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Collections.Generic;

namespace MessageWorkflow.Test.Graph
{
    [TestClass]
    public abstract class GraphTest
    {
        public Dictionary<string, string[]> TestData = new Dictionary<string, string[]>
        {
            {"Amsterdam", new string[] { }},
            {"Paris", new[] {"Amsterdam"}},
            {"Rome", new[] { "Paris" }},
            {"HongKong", new[] { "Rome" }},
            {"Shanghai", new[] { "HongKong" }},
            {"Tokyo", new[] { "Shanghai", "HongKong" }},
            {"Chicago", new[] {"Shanghai" }},
            {"New York", new[] { "Chicago", "Tokyo" }},
            {"London", new[] { "New York" }},
        };

        public void LoadTestData(IGraph<string> graph)
        {
            graph.Clear();

            foreach (var entry in TestData)
            {
                graph.Add(entry.Key, entry.Value);
            }
        }

        public abstract IGraph<string> CreateEmptyGraph();
           
        [TestMethod]
        public void Nodes_Can_Be_Added()
        {
            var graph = CreateEmptyGraph();

            int counter = 0;

            foreach (var entry in TestData)
            {
                graph.Add(entry.Key, entry.Value);

                Assert.IsTrue(graph.Nodes.Count() == ++counter);

                // make sure no existing predecessors to this value exists
                var existingDependencies = graph.GetPredecessors(entry.Key);

                Assert.IsTrue(existingDependencies.Count() == entry.Value.Count());
            }
        }

        [TestMethod]
        public void Nodes_Can_Be_Removed()
        {
            var graph = CreateEmptyGraph();
            LoadTestData(graph);

            int counter = TestData.Keys.Count;

            foreach (var node in TestData.Select(x => x.Key))
            {
                graph.Remove(node);

                Assert.IsTrue(graph.Nodes.Count() == --counter);

                // make sure no existing predecessors to this value exists
                var existingDependencies = from v in graph.Nodes
                                           from d in graph.GetPredecessors(v)
                                           where d == node
                                           select v;

                Assert.IsFalse(existingDependencies.Any());
            }
        }

        [TestMethod]
        public void Dependency_Can_Be_Detected()
        {
            var graph = CreateEmptyGraph();
            LoadTestData(graph);

            try
            {
                graph.AddPredecessors("Amsterdam", new[] { "Rome" });

                Assert.Fail("Dependency conflict should have occoured");
            }
            catch (MessageWorkflow.Graph.RecursivePathException)
            {
                // should get this
            }
        }
    }
}
